//package com.wxzz.elearning.gateway.filter.pre;
//
//import cn.hutool.core.util.StrUtil;
//import com.alibaba.fastjson.JSON;
//import com.alibaba.fastjson.JSONObject;
//import com.google.common.collect.Sets;
//import com.wxzz.elearning.common.bean.JWTResult;
//import com.wxzz.elearning.common.constants.CommonConstants;
//import com.wxzz.elearning.common.jgenum.ResponseMsgCode;
//import com.wxzz.elearning.common.utils.JWTUtils;
//import com.wxzz.elearning.common.utils.ServerConfigConmonUtil;
////import com.sie.iot.common.bean.SIEJWTResult;
////import com.sie.iot.common.util.SIEJWTUtils;
//import io.jsonwebtoken.Claims;
//import org.apache.commons.lang3.StringUtils;
//import org.slf4j.Logger;
//import org.slf4j.LoggerFactory;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.cloud.gateway.filter.GatewayFilterChain;
//import org.springframework.cloud.gateway.filter.GlobalFilter;
//import org.springframework.core.Ordered;
//import org.springframework.core.io.buffer.DataBuffer;
//import org.springframework.data.redis.core.HashOperations;
//import org.springframework.data.redis.core.RedisTemplate;
//import org.springframework.data.redis.core.ValueOperations;
//import org.springframework.data.redis.serializer.RedisSerializer;
//import org.springframework.data.redis.serializer.StringRedisSerializer;
//import org.springframework.http.HttpStatus;
//import org.springframework.http.server.reactive.ServerHttpRequest;
//import org.springframework.http.server.reactive.ServerHttpResponse;
//import org.springframework.stereotype.Component;
//import org.springframework.web.server.ServerWebExchange;
//import reactor.core.publisher.Flux;
//import reactor.core.publisher.Mono;
//
//import java.util.Iterator;
//import java.util.Set;
//import java.util.UUID;
//import java.util.concurrent.TimeUnit;
//
///**
// * 描述: 过滤器 token
// *
// * @author
// * @create 2017-12-11 14:38
// **/
////@Component
//public class TokenFilter implements GlobalFilter, Ordered {
//    private final Logger LOGGER = LoggerFactory.getLogger(TokenFilter.class);
//    private static final String MES_KEY_PRE_CN = "msg_cn";
//    private static final String MES_KEY_PRE_EN = "msg_en";
//    @Autowired
//    private RedisTemplate redisTemplate;
//    @Override
//    public int getOrder() {
//        return -1000;
//    }
//    @Override
//    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
//        RedisSerializer<String> stringSerializer = new StringRedisSerializer();
//        redisTemplate.setKeySerializer(stringSerializer);
//        redisTemplate.setValueSerializer(stringSerializer);
//        ServerHttpRequest request = exchange.getRequest();
//        //String tokenAuthorization = request.getHeader("authorization");
//        String requestURL = request.getPath().value();
//        //LOGGER.info("--->>> TokenFilter {},{}, {}", request.getMethod(), requestURL, tokenAuthorization);
//
//
//        //在处理请求之前先把token放入response
//        String token = request.getHeaders().getFirst("authorization");
//        if(StringUtils.isEmpty(token)){
//            token = request.getQueryParams().getFirst("authorization");
//        }
//        String refreToken = request.getHeaders().getFirst("refresh-authorization");
//        if(StrUtil.isNotBlank(token)){
//            exchange.getResponse().getHeaders().set("authorization",token);
//        }
//        if (StrUtil.isNotBlank(refreToken)){
//            exchange.getResponse().getHeaders().set("refresh-authorization",refreToken);
//        }
//
//
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        Set<String> whiteStrList = Sets.newHashSet();
//        whiteStrList.add("base-pa");
//        whiteStrList.add("login");
//        whiteStrList.add("api-docs");
//        whiteStrList.add("anth-num-phone");
//        whiteStrList.add("register-tenant");
//        whiteStrList.add("anth-code");
//        whiteStrList.add("anth-num");
//        whiteStrList.add("/api/external");
//        //代码生成
//        whiteStrList.add("codegen");
//        whiteStrList.add("get-api-tree");
//        whiteStrList.add("im");
//        whiteStrList.add("pre-captcha");
//
//        for(String s : whiteStrList){
//            if(requestURL.indexOf(s) >= 0){
//                return chain.filter(exchange);
//            }
//        }
//        //开放白名单的服务
//        Set<String> authorizationSet = hashOperations.keys("zuulAuthorization");
//        authorizationSet.add("export");
//        Iterator<String> iterator = authorizationSet.iterator();
//        while (iterator.hasNext()) {
//            String key = iterator.next();
//            if (key.equals("all") || requestURL.indexOf(key) >= 0) {
//                //如果是登录接口，直接路由
//                return chain.filter(exchange);
//            }
//        }
////        //如果header中authorization不存在，就从请求参数中抓取token的参数
////        if (StringUtils.isEmpty(tokenAuthorization)) {
////            tokenAuthorization = request.getParameter("token");
////        }
//        //第三方系统token校验
//        String thirdToken = request.getHeaders().getFirst("authorization_third");
//        if(null != thirdToken && !"".equals(thirdToken)){
//            //validate 第三方访问系统的token
//            JWTResult siejwtResult = JWTUtils.validateJWT(thirdToken);
//            if (null != siejwtResult && siejwtResult.isSuccess()) {
//                ValueOperations valueOperations = redisTemplate.opsForValue();
//                String redisTokenKey = valueOperations.get(thirdToken) != null ? String.valueOf(valueOperations.get(thirdToken)) : "";
//                if(null != redisTokenKey){
//                    return chain.filter(exchange);
//                }else{
//                    return tokenInvalid(exchange.getResponse());
//                }
//            }else{
//                return tokenInvalid(exchange.getResponse());
//            }
//        }
//        return checkToken(exchange,chain);
//
//
//    }
//
//
//    /**
//     * 校验刷新token  并将新的token放入response header 中
//     * 如果过期 校验token_refresh
//     * @param exchange
//     */
//    private Mono<Void> checkToken(ServerWebExchange exchange, GatewayFilterChain chain) {
//        String allow_multiple_login = ServerConfigConmonUtil.get("ALLOW_MULTIPLE_LOGIN", redisTemplate);
//        Boolean aBoolean = true;
//        if (allow_multiple_login!=null){
//            aBoolean = Boolean.valueOf(allow_multiple_login);
//        }
//
//        ServerHttpRequest  request =  exchange.getRequest();
//        //获取token 和 refreshToken
//        String token =  request.getHeaders().getFirst("authorization");
//        if(StringUtils.isEmpty(token)){
//            token = request.getQueryParams().getFirst("authorization");
//        }
//        String refreToken = request.getHeaders().getFirst("refresh-authorization");
//
////        if (StrUtil.isNotBlank(token)&&(StrUtil.isBlank(refreToken)||StrUtil.equals("undefined",refreToken))){
////            return refretokenInvalid(exchange.getResponse());
////        }
//
//        String sessionKey = "";
//        String loginFrom ;
//        if (token==null) {
//            return tokenInvalid(exchange.getResponse());
//        }
//
//        JWTResult siejwtResult = JWTUtils.validateJWT(token);
//        if (null != siejwtResult && siejwtResult.isSuccess()) {
//            //校验通过
//            Claims claims = siejwtResult.getClaims();
//            String subString = (String) claims.get("sub");
//            JSONObject subJsonObject = JSONObject.parseObject(subString);
//            String username = subJsonObject.getString("username");
//            String phoneNumber = subJsonObject.getString("phoneNumber");
//            loginFrom = subJsonObject.getString("loginFrom");
//            ValueOperations valueOperations = redisTemplate.opsForValue();
//
//            //tokenKey  refreTokenKey
//            String tokenKey = "token:" + username + phoneNumber + loginFrom;
//            String tokenRefreshKey = "refresh_token:" + username + phoneNumber + loginFrom;
//            Object redisTokenObject = valueOperations.get(tokenKey);
//            Object redisRefreshTokenObject = valueOperations.get(tokenRefreshKey);
//            String redisToken =  redisTokenObject!= null ? String.valueOf(redisTokenObject) : "";
//            String redisRefreshToken =  redisRefreshTokenObject!= null ? String.valueOf(redisRefreshTokenObject) : "";
//            if(!aBoolean){
//                //不允许多地登陆  直接校验redis中的token和refreshtoken 至少有一个和token一致  不然就要被踢掉
//                if (!StrUtil.equals(token,redisToken)&&!StrUtil.equals(token,redisRefreshToken)){
//                    return multipleLoginInvalid(exchange.getResponse());
//                }
//            }
//            //填充sessionKey
//            sessionKey = "session:" + username + phoneNumber + loginFrom;
//        }else if(null !=refreToken&&null != siejwtResult&&siejwtResult.getErrCode()== JWTUtils.JWT_ERRCODE_EXPIRE){
//            //过期 自动刷新
//            siejwtResult = JWTUtils.validateJWT(refreToken);
//            if(null != siejwtResult && siejwtResult.isSuccess()){
//                //refre_token校验通过
//                Claims claims = siejwtResult.getClaims();
//                String subString = (String) claims.get("sub");
//                JSONObject subJsonObject = JSONObject.parseObject(subString);
//                String username = subJsonObject.getString("username");
//                String phoneNumber = subJsonObject.getString("phoneNumber");
//                loginFrom = subJsonObject.getString("loginFrom");
//                //tokenKey  refreTokenKey
//                String tokenKey = "token:" + username + phoneNumber + loginFrom;
//                String tokenRefreshKey = "refresh_token:" + username + phoneNumber + loginFrom;
//
//
//                //对比redis中key value值 校验token是否已经被刷新
//                ValueOperations valueOperations = redisTemplate.opsForValue();
//                Object redisTokenObject = valueOperations.get(tokenKey);
//                Object redisRefreshTokenObject = valueOperations.get(tokenRefreshKey);
//                String redisToken =  redisTokenObject!= null ? String.valueOf(redisTokenObject) : "";
//                String redisRefreshToken =  redisRefreshTokenObject!= null ? String.valueOf(redisRefreshTokenObject) : "";
//
//                if(!aBoolean){
//                    //不允许多地登陆  直接校验redis中的token和refreshtoken 至少有一个和token一致  不然就要被踢掉
//                    if (!StrUtil.equals(refreToken,redisToken)&&!StrUtil.equals(refreToken,redisRefreshToken))
//                        return multipleLoginInvalid(exchange.getResponse());
//                }
//
//                if(refreToken.equals(redisRefreshToken)){
//                    //没有刷新  需要本次进行刷新
//                    token = redisRefreshToken;
//                    //设置新token过期时间 和redis中refreToken将失效时间保持一致
//                    valueOperations.set(tokenKey, token,redisTemplate.getExpire(tokenRefreshKey,TimeUnit.SECONDS) , TimeUnit.SECONDS);
//                    //生成新的refresh_token 并设置时redis里面的失效时间
//                    if("pc".equalsIgnoreCase(loginFrom)){
//                        refreToken = JWTUtils.createJWT(UUID.randomUUID().toString(), "wxzz-learn-jwt", subJsonObject.toJSONString(), CommonConstants.COOKIE_EXPIRED_PC*2*1000);
//                        valueOperations.set(tokenRefreshKey, refreToken, CommonConstants.COOKIE_EXPIRED_PC*2, TimeUnit.SECONDS);
//
//                    }else if ("app".equalsIgnoreCase(loginFrom)){
//                        refreToken = JWTUtils.createJWT(UUID.randomUUID().toString(), "wxzz-learn-jwt", subJsonObject.toJSONString(), CommonConstants.COOKIE_EXPIRED_APP*2*1000);
//                        valueOperations.set(tokenRefreshKey, refreToken, CommonConstants.COOKIE_EXPIRED_APP*2, TimeUnit.SECONDS);
//                    }
//                }else if(refreToken.equals(redisToken)||aBoolean){
//                    //已经刷新  读取替换即可
//                    token = redisToken;
//                    refreToken = redisRefreshToken;
//                }else{
//                    //未知情况
//                    return tokenInvalid(exchange.getResponse());
//                }
//            }else{
//                //refretoken 也过期
//                return tokenInvalid(exchange.getResponse());
//            }
//
//        }else{
//            return tokenInvalid(exchange.getResponse());
//        }
//
//        //刷新 sessionKey
//        if("pc".equalsIgnoreCase(loginFrom)) {
//            redisTemplate.expire(sessionKey, CommonConstants.COOKIE_EXPIRED_PC*2, TimeUnit.SECONDS);
//        }else if ("app".equalsIgnoreCase(loginFrom)){
//            redisTemplate.expire(sessionKey, CommonConstants.COOKIE_EXPIRED_APP*2, TimeUnit.SECONDS);
//        }
//
//        ServerHttpRequest serverHttpRequest = null;
//        //设置刷新后的token
//        exchange.getResponse().getHeaders().set("authorization",token);
//        if (StrUtil.isNotBlank(refreToken)){
//            exchange.getResponse().getHeaders().set("refresh-authorization",refreToken);
//            serverHttpRequest = exchange.getRequest().mutate().header("authorization", token).header("refresh-authorization", refreToken).build();
//        }else{
//            serverHttpRequest = exchange.getRequest().mutate().header("authorization", token).build();
//        }
//        //return chain.filter(exchange);
//        return chain.filter(exchange.mutate().request(serverHttpRequest).build());
//    }
//
//
//    private Mono<Void> tokenInvalid(ServerHttpResponse serverHttpResponse) {
//        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        serverHttpResponse.setStatusCode(HttpStatus.OK);
//        JSONObject result = new JSONObject();
//        result.put("code", "-1");
//        result.put("msgCode", ResponseMsgCode.ILLEGAL_TOKEN.msgCode);
//        result.put("msg", hashOperations.get(MES_KEY_PRE_CN, ResponseMsgCode.ILLEGAL_TOKEN.msgCode));
//        result.put("msg_en", hashOperations.get(MES_KEY_PRE_EN, ResponseMsgCode.ILLEGAL_TOKEN.msgCode));
//
//        DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
//        return serverHttpResponse.writeWith(Flux.just(dataBuffer));
//    }
//
//    private Mono<Void> multipleLoginInvalid(ServerHttpResponse serverHttpResponse) {
//        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        serverHttpResponse.setStatusCode(HttpStatus.OK);
//        JSONObject result = new JSONObject();
//        result.put("code", "-1");
//        result.put("msgCode", ResponseMsgCode.MULTIPLE_ILLEGAL_TOKEN.msgCode);
//        result.put("msg", hashOperations.get(MES_KEY_PRE_CN, ResponseMsgCode.MULTIPLE_ILLEGAL_TOKEN.msgCode));
//        result.put("msg_en", hashOperations.get(MES_KEY_PRE_EN, ResponseMsgCode.MULTIPLE_ILLEGAL_TOKEN.msgCode));
//
//        DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
//        return serverHttpResponse.writeWith(Flux.just(dataBuffer));
//    }
//
//
//    private Mono<Void> refretokenInvalid(ServerHttpResponse serverHttpResponse) {
//        serverHttpResponse.getHeaders().add("Content-Type", "application/json;charset=UTF-8");
//        HashOperations hashOperations = redisTemplate.opsForHash();
//        serverHttpResponse.setStatusCode(HttpStatus.OK);
//        JSONObject result = new JSONObject();
//        result.put("code", "805");
//        result.put("msgCode", "fk");
//        result.put("msg", "请求必须携带refreshToken，请到群里@相关模块负责人修改此功能。auth、eam：@龙勇生。 iot：@杨诗斌。");
//        result.put("msg_en", "请求必须携带refreshToken，请到群里@相关模块负责人修改此功能。auth、eam：@龙勇生。 iot：@杨诗斌。");
//
//        DataBuffer dataBuffer = serverHttpResponse.bufferFactory().wrap(JSON.toJSONString(result).getBytes());
//        return serverHttpResponse.writeWith(Flux.just(dataBuffer));
//    }
//
//
//}
